#pragma once
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

class Channel
{
public:
    Channel(int wfd, pid_t subpid)
        : _wfd(wfd), _subpid(subpid)
    {
        _name = "channel " + std::to_string(_subpid);
    }

    void Send(int code)
    {
        write(_wfd, &code, sizeof(code));
    }

    void Close()
    {
        close(_wfd);
        std::cout << "close :" << _name << std::endl;
    }

    void Wait()
    {
        waitpid(_subpid, nullptr, 0);
        std::cout << "recycle child :" << _name << std::endl;
    }
    int GetWfd()
    {
        return _wfd;
    }

    pid_t GetSubpid()
    {
        return _subpid;
    }

    std::string GetName()
    {
        return _name;
    }
    ~Channel()
    {
    }

private:
    int _wfd;
    std::string _name;
    pid_t _subpid;
};

class ChannelManager
{
public:
    Channel &Select() // 选择信道
    {
        _next++;
        _next = _next % _Channels.size();
        return _Channels[_next];
    }

    void Insert(int wfd, pid_t subpid)
    {
        _Channels.push_back(Channel(wfd, subpid));
    }

    void StopSubProcess()
    {
        for (auto &channel : _Channels)
        {
            channel.Close();
        }
    }

    void WaitSubProcess()
    {
        for (auto &channel : _Channels)
        {
            channel.Wait();
        }
    }

private:
    std::vector<Channel> _Channels;
    int _next;
};

class ProcessPool
{
public:
    ProcessPool(int num)
        : _num(num)
    {
        _tm.Register(UpLoad);
        _tm.Register(Load);
        _tm.Register(DownLoad);
    }

    void Run()
    {
        Channel &cn = _cm.Select();
        int code = _tm.Code();
        std::cout << "子进程执行：" << code << std::endl;
        _tm.Execute(code);
    }
    void Work(int rfd)
    {
        while (true)
        {
            ssize_t task_code = 0;
            int ret = read(rfd, &task_code, sizeof(task_code));
            if (ret > 0) // 子进程成功读到任务开始执行
            {
                Run();
            }
            else if (ret == 0) // 父进程W端关闭，子进程也要关闭R端
            {
                break;
            }
            else if (ret == -1) // 子进程读取失败
            {
                continue;
            }
        }
    }
    bool Start()
    {
        for (int i = 0; i < _num; i++)
        {
            int sign[2];
            int ret = pipe(sign);
            if (ret != 0)
            {
                std::cerr << "Creat pipe failed!" << std::endl;
                return false;
            }

            pid_t pid = fork();
            if (pid == 0)
            {
                // child
                close(sign[1]);
                Work(sign[0]);
                close(sign[2]);
                exit(0);
            }

            if (pid == -1)
            {
                std::cerr << "Creat child process failed!" << std::endl;
                return false;
            }

            // father
            close(sign[0]);
            _cm.Insert(sign[1], pid);
            close(sign[1]);
        }
        return true;
    }
    void Stop()
    {
        _cm.StopSubProcess();
        _cm.WaitSubProcess();
    }
    ~ProcessPool()
    {
    }

private:
    ChannelManager _cm; // 信道管理
    Task_Manager _tm;   // 任务管理
    int _num;           // 信道个数
};
